package web

import (
	"errors"
	"github.com/goccy/go-json"
	"net/http"
	"net/url"
	"strconv"
)

//var (
//	JSONUseNumber            = true
//	JSONDisableUnknownFields = true
//)

type Context struct {
	Req *http.Request
	// 如果用了Resp,就绕开了RespData和RespStatusCode,
	// 部分middleware可能无法运作
	Resp       http.ResponseWriter
	PathParams map[string]string

	// 主要是为了给middleware用
	RespData       []byte
	RespStatusCode int

	queryValues url.Values

	MatchedRoute string

	tplEngine TemplateEngine
	//cookieSameSite http.SameSite

	UserValues map[string]any // 缓存
}

func (c *Context) Render(tplName string, data any) error {
	var err error
	c.RespData, err = c.tplEngine.Render(c.Req.Context(), tplName, data)
	if err != nil {
		c.RespStatusCode = http.StatusInternalServerError
		return err
	}
	c.RespStatusCode = http.StatusOK
	return nil
}

func (c *Context) SetCookie(ck *http.Cookie) {
	// 不推荐
	//ck.SameSite = c.cookieSameSite
	// 早期没有这个api,是自己手动拼的cookie
	http.SetCookie(c.Resp, ck)
}

func (c *Context) RespJsonOK(val any) error {
	return c.RespJson(http.StatusOK, val)
}

func (c *Context) RespJson(code int, val any) error {
	data, err := json.Marshal(val)
	if err != nil {
		return err
	}
	//c.Resp.WriteHeader(code) // 状态码
	//// 参数1,写了多少数据
	//n, err := c.Resp.Write(data)
	//if n != len(data) {
	//	return errors.New("web: 未写入全部数据")
	//}
	c.RespData = data
	c.RespStatusCode = code
	return err
}

func (c *Context) BindJSON(val any) error {
	//if val == nil {
	//	return errors.New("web: 输入为nil")
	//}
	if c.Req.Body == nil {
		return errors.New("web: Body为nil")
	}
	decoder := json.NewDecoder(c.Req.Body)
	//if JSONUseNumber {
	//	decoder.UseNumber()
	//}
	//if JSONDisableUnknownFields {
	//	decoder.DisallowUnknownFields()
	//}
	return decoder.Decode(val)
}

//func (c *Context) BindJSON(val any, useNum bool, disable bool) error {
//}

func (c *Context) FormValue(key string) (string, error) {
	err := c.Req.ParseForm()
	if err != nil {
		return "", err
	}
	//vals, ok := c.Req.Form[key]
	//if !ok {
	//	return "", errors.New("web: key 不存在")
	//}
	//return vals[0], nil
	return c.Req.FormValue(key), nil
}

func (c *Context) QueryValue(key string) (string, error) {
	if c.queryValues == nil {
		// Query每次会调用parseQuery,而form只调用一次,所以query需要缓存
		// 缓存
		c.queryValues = c.Req.URL.Query()
	}
	vals, ok := c.queryValues[key]
	if !ok {
		return "", errors.New("web: key 不存在")
	}
	return vals[0], nil
}

func (c *Context) QueryValueV1(key string) StringValue {
	if c.queryValues == nil {
		// Query每次会调用parseQuery,而form只调用一次,所以query需要缓存
		// 缓存
		c.queryValues = c.Req.URL.Query()
	}
	vals, ok := c.queryValues[key]
	if !ok {
		return StringValue{
			err: errors.New("web: key 不存在"),
		}
	}
	return StringValue{
		val: vals[0],
	}
}

func (c *Context) PathValue(key string) (string, error) {
	val, ok := c.PathParams[key]
	if !ok {
		return "", errors.New("web: key 不存在")
	}
	return val, nil
}

func (c *Context) PathValueV1(key string) StringValue {
	val, ok := c.PathParams[key]
	if !ok {
		return StringValue{
			err: errors.New("web: key 不存在"),
		}
	}
	return StringValue{val: val}
}

type StringValue struct {
	val string
	err error
}

func (s StringValue) AsInt64() (int64, error) {
	if s.err != nil {
		return 0, s.err
	}
	return strconv.ParseInt(s.val, 10, 64)
}
